Namespace Functions

    Module mLoginFunctions

        Public Function GetLoginID(ByVal username As String) As Integer

            Dim sSql As String = "SELECT ID_LOGIN FROM TBL_LOGINS WHERE STR_USERNAME='" & username & "';"
            Dim row As Collection = DB.AccountDB.ExecuteQueryFirstRecord(sSql)

            If row Is Nothing Then Return 0
            If row.Count = 0 Then Return 0

            Return row("ID_LOGIN")

        End Function

        Public Function GetCharID(ByVal name As String) As Integer

            Dim sSql As String = "SELECT ID_CHARACTER FROM TBL_CHARACTER WHERE STR_NAME='" & name & "';"
            Dim row As Collection = DB.GameDB.ExecuteQueryFirstRecord(sSql)

            If row Is Nothing Then Return 0
            If row.Count = 0 Then Return 0

            Return row("ID_CHARACTER")
            
        End Function

        Public Function CreateAccount(ByVal struct As NewUserLogin, ByVal isgm As Boolean, Optional ByVal showoutput As Boolean = False, Optional ByRef outputtext As String = Nothing) As Boolean

            If struct.STR_USERNAME.Length < MIN_USERNAME_LEN Then
                outputtext = "Username field must be at least " & MIN_USERNAME_LEN & " characters!"
                If showoutput Then Output.AddLine("# " & outputtext)
                Return False
            End If

            If struct.STR_USERNAME.Length > MAX_USERNAME_LEN Then
                outputtext = "Username field must be " & MAX_USERNAME_LEN & " characters or less!"
                If showoutput Then Output.AddLine("# " & outputtext)
                Return False
            End If

            If GetLoginID(struct.STR_USERNAME) > 0 Then
                outputtext = "That username already exists!"
                If showoutput Then Output.AddLine("# " & outputtext)
                Return False
            End If

            If InStr(struct.STR_EMAIL, "@") + InStr(struct.STR_EMAIL, ".") = 0 Then
                outputtext = "That email is invalid!"
                If showoutput Then Output.AddLine("# " & outputtext)
                Return False
            End If

            Dim cols() As String = {"STR_USERNAME", "STR_PASSMD5", "STR_EMAIL", "BYTE_ATTEMPTS", "BYTE_SELECTED", "BOOL_DELETED"}
            Dim vals() As String = {"'" & struct.STR_USERNAME & "'", "'" & struct.STR_PASSMD5 & "'", "'" & struct.STR_EMAIL & "'", "0", "0", "'FALSE'"}

            If DB.AccountDB.NewRecord("TBL_LOGINS", cols, vals) = 0 Then
                outputtext = "Account Creation Failed!"
                If showoutput Then Output.AddLine("# " & outputtext)
                Return False
            End If

            outputtext = "Account created!"
            If showoutput Then Output.AddLine("# " & outputtext)

            If isgm Then
                If Not SetGMRights(struct.STR_USERNAME, False, True, True) Then
                    Return False
                End If
            End If

            Return True

        End Function

        Public Function DeleteAccount(ByVal loginid As Integer, ByVal enable As Boolean, Optional ByVal showoutput As Boolean = False) As Boolean

            If loginid = 0 Then
                If showoutput Then Output.AddLine("# LoginID does not exist!")
                Return False
            Else
                Dim sSql As String = "UPDATE TBL_LOGINS SET BOOL_DELETED='" & (Not enable).ToString & "' WHERE ID_LOGIN=" & loginid & "';"
                DB.AccountDB.ExecuteNonQuery(sSql)
            End If

            If enable Then
                If showoutput Then Output.AddLine("# LoginID #" & loginid & "' enabled!")
            Else
                If showoutput Then Output.AddLine("# LoginID #" & loginid & " deleted!")
            End If

            Return False

        End Function

        Public Function DeleteAccount(ByVal username As String, ByVal enable As Boolean, Optional ByVal showoutput As Boolean = False) As Boolean

            DeleteAccount(GetLoginID(username), enable, showoutput)

        End Function

        Public Function SetGMRights(ByVal loginid As Integer, ByVal ignoreipfilter As Boolean, ByVal isgm As Boolean, Optional ByVal showoutput As Boolean = False) As Boolean

            If loginid = 0 Then
                If showoutput Then Output.AddLine("# Username does not exist!")
                Return False
            Else

                Dim sSql As String = "UPDATE TBL_GAMEMASTERLOGINS SET BOOL_DELETED='TRUE' WHERE ID_LOGIN=" & loginid & ";"
                DB.AccountDB.ExecuteNonQuery(sSql)

                If isgm Then

                    Dim cols() As String = {"ID_LOGIN", "BOOL_IGNOREFILTER", "BOOL_DELETED"}
                    Dim vals() As String = {loginid.ToString, "'" & ignoreipfilter.ToString & "'", "'FALSE'"}

                    If Not DB.AccountDB.NewRecord("TBL_GAMEMASTERLOGINS", cols, vals) Then
                        If showoutput Then Output.AddLine("# GM rights assigned!")
                        Return True
                    End If

                End If

            End If

            If showoutput Then Output.AddLine("# GM Rights Assignment Failed!")
            Return False

        End Function

        Public Function SetGMRights(ByVal username As String, ByVal ignoreipfilter As Boolean, ByVal isgm As Boolean, Optional ByVal showoutput As Boolean = False) As Boolean

            SetGMRights(GetLoginID(username), ignoreipfilter, isgm, showoutput)

        End Function

        Public Function AccountIsLocked(ByVal loginid As Integer) As Boolean

            If loginid = 0 Then
                Return True
            Else

                Dim sSql As String = "SELECT STR_TIMEOUT FROM TBL_LOCK WHERE ID_LOGIN=" & loginid & " AND BOOL_DELETED='False';"
                Dim row As Collection = DB.AccountDB.ExecuteQueryFirstRecord(sSql)

                If row Is Nothing Then Exit Function
                If row.Count > 0 Then


                    Dim timeout As Date = Date.Parse(row("STR_TIMEOUT"))
                    If timeout < Date.Now Then
                        sSql = "UPDATE TBL_LOCK SET BOOL_DELETED='True' WHERE ID_LOGIN='" & loginid & "';"
                        DB.AccountDB.ExecuteNonQuery(sSql)
                        Return False
                    Else
                        Return True
                    End If

                End If

                End If

                Return False

        End Function

        Public Function AccountIsLocked(ByVal username As String) As Boolean
            Return AccountIsLocked(GetLoginID(username))
        End Function

        Public Sub ResetLoginAttempts(ByVal loginid As Integer)

            Dim sSql As String = "UPDATE TBL_LOGINS SET BYTE_ATTEMPTS=0 WHERE ID_LOGIN=" & loginid & ";"
            DB.AccountDB.ExecuteNonQuery(sSql)

        End Sub

        Public Sub ResetLoginAttempts(ByVal username As String)

            Dim sSql As String = "UPDATE TBL_LOGINS SET BYTE_ATTEMPTS=0 WHERE STR_USERNAME='" & username & "';"
            DB.AccountDB.ExecuteNonQuery(sSql)

        End Sub

        Public Function FailedLogin(ByVal loginid As Integer) As Boolean

            If loginid = 0 Then

            Else

                Dim sSql As String = "SELECT BYTE_ATTEMPTS FROM TBL_LOGINS WHERE ID_LOGIN=" & loginid & " AND BOOL_DELETED='False';"
                Dim row As Collection = DB.AccountDB.ExecuteQueryFirstRecord(sSql)

                If row Is Nothing Then Exit Function
                If row.Count > 0 Then

                    Dim attempts As Integer = row("BYTE_ATTEMPTS") + 1

                    If attempts >= Globals.MaxLoginAttempts Then

                        Dim cols() As String = {"ID_LOGIN", "STR_TIMEOUT", "BOOL_DELETED"}
                        Dim vals() As String = {loginid, "'" & Database.Functions.TimeString(Globals.LockTime) & "'", "'FALSE'"}

                        DB.AccountDB.NewRecord("TBL_LOCK", cols, vals)
                        Logger.LoggerWriteLine("!!! ID_LOGIN #" & loginid & " locked due to excessive incorrect login attempts")
                        attempts = 0

                    End If

                    sSql = "UPDATE TBL_LOGINS SET BYTE_ATTEMPTS=" & attempts & " WHERE ID_LOGIN=" & loginid & ";"
                    DB.AccountDB.ExecuteNonQuery(sSql)

                End If

            End If

        End Function

        Public Function GetLockTimeout(ByVal username As String) As String

            Dim sSql As String = "SELECT ID_LOGIN FROM TBL_LOGINS WHERE STR_USERNAME='" & username & "' AND BOOL_DELETED='False';"
            Dim row As Collection = DB.AccountDB.ExecuteQueryFirstRecord(sSql)

            If row Is Nothing Then Return ""
            If row.Count > 0 Then

                sSql = "SELECT STR_TIMEOUT FROM TBL_LOCK WHERE ID_LOGIN=" & row("ID_LOGIN") & " AND BOOL_DELETED='False';"
                row = DB.AccountDB.ExecuteQueryFirstRecord(sSql)

                If row Is Nothing Then Return ""

                If row.Count > 0 Then
                    Return row("STR_TIMEOUT")
                End If

            End If

            Return ""

        End Function

        Public Function GetSelCharList(ByVal loginid As Integer) As SelCharList

            Dim struct As New SelCharList

            Dim sSql As String = "SELECT c.ID_CHARACTER, c.STR_NAME, s.INT2_LEVEL , c.BYTE_JOB, c.BYTE_SEX" & _
                " FROM TBL_CHARACTER c JOIN TBL_BASESTATS s" & _
                " ON c.ID_CHARACTER = s.ID_CHARACTER" & _
                " WHERE c.ID_LOGIN=" & loginid & " AND c.BOOL_DELETED='False' ORDER BY c.ID_CHARACTER ASC;"
            Dim row As ArrayList = DB.GameDB.ExecuteQuery(sSql)

            struct.CHAR_2.ID_CHARACTER = 0
            struct.CHAR_2.STR_NAME = ""
            struct.CHAR_2.BYTE_JOB = 0
            struct.CHAR_2.BYTE_SEX = 0
            struct.CHAR_2.INT2_LEVEL = 0
            struct.CHAR_2.ID_CHARACTER = 0
            struct.CHAR_2.STR_NAME = ""
            struct.CHAR_2.BYTE_JOB = 0
            struct.CHAR_2.BYTE_SEX = 0
            struct.CHAR_2.INT2_LEVEL = 0
            struct.BYTE_SELECTED = 0

            If Not row Is Nothing Then

                If row.Count >= 1 Then
                    struct.CHAR_1.ID_CHARACTER = row(0)("ID_CHARACTER")
                    struct.CHAR_1.STR_NAME = row(0)("STR_NAME")
                    struct.CHAR_1.BYTE_JOB = row(0)("BYTE_JOB")
                    struct.CHAR_1.BYTE_SEX = row(0)("BYTE_SEX")
                    struct.CHAR_1.INT2_LEVEL = row(0)("INT2_LEVEL")
                    If row.Count >= 2 Then
                        struct.CHAR_2.ID_CHARACTER = row(1)("ID_CHARACTER")
                        struct.CHAR_2.STR_NAME = row(1)("STR_NAME")
                        struct.CHAR_2.BYTE_JOB = row(1)("BYTE_JOB")
                        struct.CHAR_2.BYTE_SEX = row(1)("BYTE_SEX")
                        struct.CHAR_2.INT2_LEVEL = row(1)("INT2_LEVEL")
                    End If
                End If
            End If

            sSql = "SELECT BYTE_SELECTED FROM TBL_LOGINS WHERE ID_LOGIN=" & loginid & ";"
            Dim col As Collection = DB.AccountDB.ExecuteQueryFirstRecord(sSql)

            If col Is Nothing Then Return Nothing
            If col.Count = 0 Then Return Nothing

            struct.BYTE_SELECTED = col("BYTE_SELECTED")

            Return struct

        End Function

        Public Function GetLevel(ByVal characterid As Integer) As Int16

        End Function

        Public Function HasSpareSlots(ByVal loginid As Integer) As Boolean

            Dim sSql As String = "SELECT ID_CHARACTER FROM TBL_CHARACTER WHERE ID_LOGIN=" & loginid & " AND BOOL_DELETED='False';"
            Dim row As ArrayList = DB.GameDB.ExecuteQuery(sSql)

            If row Is Nothing Then Exit Function

            If row.Count < MAX_CHARS Then
                Return True
            Else
                Return False
            End If

        End Function

        Public Sub WriteFreshBaseStats(ByVal characterid As Int64, ByVal job As CharacterJobs)

            Dim ssql As String = "SELECT * FROM TBL_DEFAULTSTATS WHERE BYTE_JOB=" & job & ";"
            Dim stats As Collection = DB.GameDB.ExecuteQueryFirstRecord(ssql)

            If stats Is Nothing Then Exit Sub
            If stats.Count = 0 Then Exit Sub

            Dim cols() As String = {"ID_CHARACTER", "INT2_LEVEL", "INT8_EXP", _
                                    "INT1_EXPBONUS", "INT2_MIN_AC", "INT2_MIN_MAC", _
                                    "INT2_MIN_DC", "INT2_MIN_MC", "INT2_MIN_SC", _
                                    "INT2_MAX_HP", "INT2_MAX_MP", "INT2_MAX_AC", _
                                    "INT2_MAX_MAC", "INT2_MAX_DC", "INT2_MAX_MC", _
                                    "INT2_MAX_SC", "INT2_MAX_WEIGHT", "INT2_MAX_HANDWEIGHT", _
                                    "INT2_MAX_WEARWEIGHT", "INT2_ELEMC_FIRE", "INT2_ELEMC_ICE", _
                                    "INT2_ELEMC_LIGHT", "INT2_ELEMC_WIND", "INT2_ELEMC_HOLY", _
                                    "INT2_ELEMC_DARK", "INT2_ELEMC_PHANTOM", "INT2_ELEMAC_FIRE", _
                                    "INT2_ELEMAC_ICE", "INT2_ELEMAC_LIGHT", "INT2_ELEMAC_WIND", _
                                    "INT2_ELEMAC_HOLY", "INT2_ELEMAC_DARK", "INT2_ELEMAC_PHANTOM", _
                                    "INT1_ACCURACY", "INT1_AGILITY", "INT1_VELOCITY", _
                                    "INT1_BODYLUCK"}

            Dim vals() As String = {characterid, stats("INT2_LEVEL"), stats("INT8_EXP"), _
                                    stats("INT1_EXPBONUS"), stats("INT2_MIN_AC"), stats("INT2_MIN_MAC"), _
                                    stats("INT2_MIN_DC"), stats("INT2_MIN_MC"), stats("INT2_MIN_SC"), _
                                    stats("INT2_MAX_HP"), stats("INT2_MAX_MP"), stats("INT2_MAX_AC"), _
                                    stats("INT2_MAX_MAC"), stats("INT2_MAX_DC"), stats("INT2_MAX_MC"), _
                                    stats("INT2_MAX_SC"), stats("INT2_MAX_WEIGHT"), stats("INT2_MAX_HANDWEIGHT"), _
                                    stats("INT2_MAX_WEARWEIGHT"), stats("INT2_ELEMC_FIRE"), stats("INT2_ELEMC_ICE"), _
                                    stats("INT2_ELEMC_LIGHT"), stats("INT2_ELEMC_WIND"), stats("INT2_ELEMC_HOLY"), _
                                    stats("INT2_ELEMC_DARK"), stats("INT2_ELEMC_PHANTOM"), stats("INT2_ELEMAC_FIRE"), _
                                    stats("INT2_ELEMAC_ICE"), stats("INT2_ELEMAC_LIGHT"), stats("INT2_ELEMAC_WIND"), _
                                    stats("INT2_ELEMAC_HOLY"), stats("INT2_ELEMAC_DARK"), stats("INT2_ELEMAC_PHANTOM"), _
                                    stats("INT1_ACCURACY"), stats("INT1_AGILITY"), stats("INT1_VELOCITY"), _
                                    stats("INT1_BODYLUCK")}

            DB.GameDB.NewRecord("TBL_BASESTATS", cols, vals)

        End Sub

        'Public Sub WriteBlankEquipment(ByVal idChar As Int64)

        'Dim sSql As String = "INSERT INTO TBL_CHARACTEREQUIPMENT (ID_CHARACTER,ID_ARMOR,ID_HELMET,ID_WEAPON) VALUES (" & idChar & ",0,0,0);"
        'DB.GameDB.ExecuteNonQuery(sSql)

        'End Sub

        Public Function SetSelectedChar(ByVal loginid As Integer, ByVal str_name As String) As Boolean

            Dim sSql As String = "SELECT STR_NAME FROM TBL_CHARACTER WHERE ID_LOGIN=" & loginid & " AND BOOL_DELETED='False' ORDER BY ID_CHARACTER ASC;"
            Dim row As ArrayList = DB.GameDB.ExecuteQuery(sSql)
            Dim byte_selected As Byte

            If row.Count < 2 Then
                byte_selected = 0
            Else
                If row(0)("STR_NAME") = str_name Then
                    byte_selected = 0
                ElseIf row(1)("STR_NAME") = str_name Then
                    byte_selected = 1
                Else
                    byte_selected = 0
                End If
            End If

            sSql = "UPDATE TBL_LOGINS SET BYTE_SELECTED=" & byte_selected & " WHERE ID_LOGIN=" & loginid & " AND BOOL_DELETED='False';"
            Return DB.AccountDB.ExecuteNonQuery(sSql)

        End Function

        Public Function GenerateSessionID() As Byte()

            'allocate an Array of 4 null bytes
            Dim sessid As Byte() = {0, 0, 0, 0}
            'set all 4 bytes to Random values between 0-255
            sessid(0) = Int(Rnd() * 255)
            sessid(1) = Int(Rnd() * 255)
            sessid(2) = Int(Rnd() * 255)
            sessid(3) = Int(Rnd() * 255)
            'return the 4 byte array to be used as a SessionID
            Return sessid

        End Function

    End Module

End Namespace